package co.gov.medellin.ssti.sub.model.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;

import co.gov.medellin.ssti.sub.model.dao.BOTEmpresaDAO;
import co.gov.medellin.ssti.sub.model.dao.exception.DAOException;
import co.gov.medellin.ssti.sub.model.service.AtributosService;
import co.gov.medellin.ssti.sub.model.vo.BOTEmpresaAtr;
import co.gov.medellin.ssti.sub.model.vo.Beneficiario_AtributoVO;
import co.gov.medellin.ssti.sub.model.vo.BeneficioOtorgadoEmpresaVO;
import co.gov.medellin.ssti.sub.model.vo.ModificarBOTVO;
import co.gov.medellin.ssti.sub.model.vo.SubprogramaSedeVO;

public class BOTEmpresaDAOImpl extends NamedParameterJdbcDaoSupport implements
		BOTEmpresaDAO {
	@Autowired
	AtributosService atributosServiceImpl;

	private static final String SELECT_SEDE_OTORGAMIENTO = "SELECT CODSEDE FROM VCS_BOT_EMPRESA "
			+ "WHERE CODBOT = :CODBOT ";

	private static final String SELECT_BENEFICIO_VALOR_NUM_ATR = "SELECT VALOR_NUM_ATR "
			+ " valor, codigo FROM TCS_BOT_EMPRESA_ATR "
			+ "WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_BENEFICIO_VALOR_FEC_ATR = "SELECT TO_CHAR(VALOR_FEC_ATR,'DD/MM/RRRR') "
			+ " valor, codigo FROM TCS_BOT_EMPRESA_ATR "
			+ "WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_BENEFICIO_VALOR_CAR_ATR = "SELECT VALOR_CAR_ATR "
			+ " valor, codigo FROM TCS_BOT_EMPRESA_ATR "
			+ "WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String TIENE_BENEFICIO = "SELECT CODIGO FROM TCS_BOT_EMPRESA "
			+ " WHERE EMP_CODIGO = :EMP_CODIGO AND SBPR_CODIGO = :SBPR_CODIGO "
			+ " AND CAMPO_A1 IS NULL";

	private static final String SELECT_MAX_COD_BENEFICIO_OTORGADO_EMPRESA_BY_SUBP_COD_BEN_COD = "SELECT MAX(CODIGO) codbot FROM TCS_BOT_EMPRESA "
			+ " WHERE SBPR_CODIGO = :SBPR_CODIGO AND EMP_CODIGO = :EMP_CODIGO ";
	// +
	// " AND FECHA_BENEFICIO=(SELECT MAX(FECHA_BENEFICIO) FROM TCS_BEN_BENEFICIO_OTORGADO "
	// + " WHERE SBPR_CODIGO = :SBPR_CODIGO AND CAMPO_N3 = :CAMPO_N3 ) "
	// + " GROUP BY SEDE_CODIGO";

	private static final String SELECT_BOT_EMPRESA_ATR_VALOR_NUM_ATR = "SELECT VALOR_NUM_ATR "
			+ " valor FROM TCS_BOT_EMPRESA_ATR WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO "
			+ " AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_BOT_EMPRESA_ATR_VALOR_FEC_ATR = "SELECT TO_CHAR(VALOR_FEC_ATR,'DD/MM/RRRR') "
			+ " valor FROM TCS_BOT_EMPRESA_ATR WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO "
			+ " AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_BOT_EMPRESA_ATR_VALOR_CAR_ATR = "SELECT VALOR_CAR_ATR "
			+ " valor FROM TCS_BOT_EMPRESA_ATR WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO "
			+ " AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String VALOR_CAR_ATR = "VALOR_CAR_ATR";
	private static final String VALOR_NUM_ATR = "VALOR_NUM_ATR";
	private static final String VALOR_FEC_ATR = "VALOR_FEC_ATR";

	@Override
	public String findSedeOtorgamientoByCodBot(Long codeBot) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String sede = "";
		namedParameters.put("CODBOT", codeBot);
		try {
			sede = getNamedParameterJdbcTemplate().queryForObject(
					SELECT_SEDE_OTORGAMIENTO, namedParameters, String.class);
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO:
		}
		return sede;
	}

	@Override
	public ModificarBOTVO findBeneficioAtri(String tipoDato,
			String codeBeneOtor, String codeAtri) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String consulta;
		if (tipoDato.equals("N")) {
			consulta = SELECT_BENEFICIO_VALOR_NUM_ATR;
		} else if (tipoDato.equals("F")) {
			consulta = SELECT_BENEFICIO_VALOR_FEC_ATR;
		} else {
			consulta = SELECT_BENEFICIO_VALOR_CAR_ATR;
		}

		int codbeneotor = Integer.parseInt(codeBeneOtor.trim());
		int codatri = Integer.parseInt(codeAtri.trim());

		ModificarBOTVO modificarBOTVO = new ModificarBOTVO();
		// System.out.println("[" + this.getClass()
		// + ".findBeneficioAtri] query: " + consulta);
		// System.out.println("BOT_EMP_CODIGO:" + codbeneotor);
		// System.out.println("SAB_CODIGO: " + codatri);

		namedParameters.put("BOT_EMP_CODIGO", codbeneotor);
		namedParameters.put("SAB_CODIGO", codatri);

		try {
			modificarBOTVO = getNamedParameterJdbcTemplate().queryForObject(
					consulta, namedParameters, new RowMapper<ModificarBOTVO>() {

						public ModificarBOTVO mapRow(ResultSet rs, int rowNum)
								throws SQLException {
							ModificarBOTVO modificarBOTVO = new ModificarBOTVO();
							modificarBOTVO.setValorInicial(rs
									.getString("valor"));
							modificarBOTVO.setCodigo(new Long(rs
									.getLong("codigo")));
							return modificarBOTVO;
						}
					});
		} catch (IncorrectResultSizeDataAccessException e) {
			return modificarBOTVO;
		}
		return modificarBOTVO;
	}

	@Override
	public boolean validarEditBOT(String groupUserName, String userName,
			Long codeBOTEmpresa) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT COUNT(1) cantidad " + " FROM VCS_BOT_EMPRESA "
				+ " WHERE ('ADMINISTRADOR GENERAL' = :GROUPUSERNAME "
				+ " OR 'SUPER USUARIO' = :GROUPUSERNAME "
				+ " OR USUARIOCREA = :USERNAME ) AND CODBOT = :CODBOT ";

		namedParameters.put("GROUPUSERNAME", groupUserName);
		namedParameters.put("USERNAME", userName);
		namedParameters.put("CODBOT", codeBOTEmpresa);

		try {
			int cantidad = getNamedParameterJdbcTemplate().queryForObject(
					query, namedParameters, Integer.class);
			if (cantidad > 0) {
				return true;
			} else {
				return false;
			}
		} catch (IncorrectResultSizeDataAccessException e) {
			return false;
		}
	}

	@Override
	public boolean updateBOTEmpresa(
			BeneficioOtorgadoEmpresaVO beneficioOtorgadoEmpresaVO,
			Long codeSedeOld, List<Beneficiario_AtributoVO> lListaInsertar) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		boolean retorno = true;
		boolean cantidad = false;

		Long codeSede = beneficioOtorgadoEmpresaVO.getSedeCodigo();
		Long codeSubprograma = beneficioOtorgadoEmpresaVO.getSbprCodigo();

		cantidad = (codeSede.longValue() == codeSedeOld.longValue()) ? true
				: checkBeneficio(new Long(codeSede.longValue()),
						codeSubprograma);
		boolean sw = false;
		if (cantidad) {
			int tamanoinsert = lListaInsertar.size();

			String query = "UPDATE TCS_BOT_EMPRESA "
					+ " SET SEDE_CODIGO = :SEDE_CODIGO , TERCERO = :TERCERO, "
					+ " FECHA_MEDICION = TO_DATE(:FECHA_MEDICION,'dd/mm/RRRR'), "
					+ " VALOR_BENEFICIO = :VALOR_BENEFICIO, "
					+ " VIGENCIA_BENEFICIO = TO_NUMBER(:VIGENCIA_BENEFICIO, 9999), "
					+ " PRESUP_TOT_EJECUTADO = :PRESUP_TOT_EJECUTADO, "
					+ " USUARIO_MODIFICA = :USUARIO_MODIFICA, "
					+ " TIPO_BENEFICIO = :TIPO_BENEFICIO, "
					+ " TERMINAL_MODIFICA = :TERMINAL_MODIFICA "
					+ " WHERE CODIGO = :CODIGO";

			namedParameters.put("SEDE_CODIGO",
					beneficioOtorgadoEmpresaVO.getSedeCodigo());
			namedParameters.put("TERCERO",
					beneficioOtorgadoEmpresaVO.getTercero());
			namedParameters.put("FECHA_MEDICION",
					beneficioOtorgadoEmpresaVO.getFechaMedicion());
			namedParameters.put("VALOR_BENEFICIO",
					beneficioOtorgadoEmpresaVO.getValorBeneficio());
			namedParameters.put("VIGENCIA_BENEFICIO",
					beneficioOtorgadoEmpresaVO.getVigenciaBeneficio());
			namedParameters.put("PRESUP_TOT_EJECUTADO",
					beneficioOtorgadoEmpresaVO.getPresupTotEjecutado());
			namedParameters.put("USUARIO_MODIFICA",
					beneficioOtorgadoEmpresaVO.getUsuarioModifica());
			namedParameters.put("TIPO_BENEFICIO",
					beneficioOtorgadoEmpresaVO.getTipoBeneficio());
			namedParameters.put("TERMINAL_MODIFICA",
					beneficioOtorgadoEmpresaVO.getTerminalModifica());
			namedParameters.put("CODIGO",
					beneficioOtorgadoEmpresaVO.getCodigo());

			int updated = getNamedParameterJdbcTemplate().update(query,
					namedParameters);

			if (updated == 1) {
				if (beneficioOtorgadoEmpresaVO.getTercero() == null) {
					sw = true;
				} else {
					if (beneficioOtorgadoEmpresaVO.getTercero().equals("")) {
						sw = true;
					}
				}

				// Proceso para actualizar la cantidad disponible
				if (sw && !codeSede.equals(codeSedeOld)) {
					// Para disminuir en uno el numero de beneficios
					// disponibles en la nueva sede
					updateBeneficioDisponible(codeSede, codeSubprograma);

					// Para aumentar en uno el numero de beneficios
					// disponibles en la nueva sede
					aumentarBeneficioDisponible(codeSedeOld, codeSubprograma);
				}
				// fin del proceso

				for (int j = 0; j < tamanoinsert; j++) {
					Beneficiario_AtributoVO objBenAtri = (Beneficiario_AtributoVO) lListaInsertar
							.get(j);

					if ((objBenAtri.getTipoatributo()).equals("R")) {
						throw new RuntimeException("R");
						// int updatedbeneficiarioatri = atributosServiceImpl
						// .insertBeneficiarioAtri(
						// objBenAtri.getVariable().trim(),
						// objBenAtri.getTipodato(),
						// new Long(objBenAtri.getCodigoatributo()),
						// new Long(objBenAtri
						// .getCodbeneficiario()), i,
						// strArrIns);

					} else {
						BOTEmpresaAtr atr = new BOTEmpresaAtr();
						atr.setSabCodigo(Long.valueOf(objBenAtri
								.getCodigoatributo()));
						atr.setBotEmpCodigo(beneficioOtorgadoEmpresaVO
								.getCodigo());
						atr.getAuditoriaVO()
								.setUsuarioModifica(
										beneficioOtorgadoEmpresaVO
												.getUsuarioModifica());
						atr.getAuditoriaVO().setTerminalModifica(
								beneficioOtorgadoEmpresaVO
										.getTerminalModifica());
						atr.getAuditoriaVO()
								.setUsuarioCrea(
										beneficioOtorgadoEmpresaVO
												.getUsuarioModifica());
						atr.getAuditoriaVO().setTerminalCrea(
								beneficioOtorgadoEmpresaVO
										.getTerminalModifica());
						atr.setTipoDato(objBenAtri.getTipodato());
						atr.setVariable(objBenAtri.getVariable().trim());

						int updatedBOTEmpresaAtr = upsertBOTEmpresaAtr(atr);

					}
				}
			} else {
				return retorno = false;
			}
		} else {
			return retorno = false;
		}
		return retorno;
	}

	// TODO:test
	public int upsertBOTEmpresaAtr(BOTEmpresaAtr atr) {

		Map<String, Object> namedParameters = new HashMap<String, Object>();
		// consulta la fecha del beneficio.
		String queryFecha = "SELECT FECHA_MEDICION FROM TCS_BOT_EMPRESA "
				+ " WHERE CODIGO = :CODIGO ";
		namedParameters.put("CODIGO", atr.getCodigo());
		java.sql.Date fecha = null;
		java.sql.Date res;
		try {
			res = getNamedParameterJdbcTemplate().queryForObject(queryFecha,
					namedParameters, java.sql.Date.class);
			atr.setFecha(res);
		} catch (IncorrectResultSizeDataAccessException e) {
			atr.setFecha(new java.sql.Date(new java.util.Date().getTime()));
		}

		// reusar map
		namedParameters.clear();

		boolean existeAtr = existeBOTEmpresaAtr(atr.getBotEmpCodigo(),
				atr.getSabCodigo());

		String nombreValorXAtr;
		String valorValorXAtr;

		if (atr.getTipoDato().equalsIgnoreCase("A")
				|| atr.getTipoDato().equalsIgnoreCase("L")) {
			nombreValorXAtr = VALOR_CAR_ATR;
			valorValorXAtr = "UPPER(:strValor)";
			namedParameters.put("dataType", VALOR_CAR_ATR);
			namedParameters.put("valor", "UPPER('" + atr.getVariable() + "')");
		} else if (atr.getTipoDato().equalsIgnoreCase("N")) {
			nombreValorXAtr = VALOR_NUM_ATR;
			valorValorXAtr = ":strValor";
			namedParameters.put("dataType", VALOR_NUM_ATR);
			namedParameters.put("valor", atr.getVariable());
		} else {
			nombreValorXAtr = VALOR_FEC_ATR;
			valorValorXAtr = "TO_DATE(:strValor,'dd/mm/rrrr')";
			namedParameters.put("dataType", VALOR_FEC_ATR);
			namedParameters.put("valor", "TO_DATE('" + atr.getVariable()
					+ "','dd/mm/rrrr')");
		}
		namedParameters.put("fecha", fecha);

		int ups = 0;

		if (!existeAtr) {
			ups = insertBOTEmpresaAtr(atr, nombreValorXAtr, valorValorXAtr);
		} else {
			ups = updateBOTEmpresaAtr(atr, nombreValorXAtr, valorValorXAtr);
		}

		if (ups == 0) {
			throw new DAOException("No se actualizo el atributo.");
		}
		return ups;
	}

	private int insertBOTEmpresaAtr(BOTEmpresaAtr atr, String nombreValorXAtr,
			String valorValorXAtr) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"INSERT INTO TCS_BOT_EMPRESA_ATR ");
		query.append("(CODIGO, BOT_EMP_CODIGO, SAB_CODIGO, ");
		query.append(nombreValorXAtr);
		query.append(", CAMPO_F1, USUARIO_CREA, FECHA_CREA, TERMINAL_CREA) ");
		query.append(" VALUES(SCS_BOT_EMP_ATR.NEXTVAL, :BOT_EMP_CODIGO, :SAB_CODIGO, ");
		query.append(valorValorXAtr);
		query.append(", :CAMPO_F1, :USUARIO_CREA, SYSDATE, :TERMINAL_CREA)");

		namedParameters.put("BOT_EMP_CODIGO", atr.getBotEmpCodigo());
		namedParameters.put("SAB_CODIGO", atr.getSabCodigo());
		namedParameters.put("CAMPO_F1", atr.getFecha());
		namedParameters.put("USUARIO_CREA", atr.getAuditoriaVO()
				.getUsuarioCrea());
		namedParameters.put("TERMINAL_CREA", atr.getAuditoriaVO()
				.getTerminalCrea());
		namedParameters.put("strValor", atr.getVariable());

		// System.out.println("query: " + query);
		// for (String str : namedParameters.keySet()) {
		// System.out.println(str + ": " + namedParameters.get(str));
		// }

		return getNamedParameterJdbcTemplate().update(query.toString(),
				namedParameters);
	}

	private int updateBOTEmpresaAtr(BOTEmpresaAtr atr, String nombreValorXAtr,
			String valorValorXAtr) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer("UPDATE TCS_BOT_EMPRESA_ATR SET ");
		query.append(nombreValorXAtr);
		query.append(" = ");
		query.append(valorValorXAtr);
		query.append(" , USUARIO_MODIFICA = :USUARIO_MODIFICA, CAMPO_F1 = :CAMPO_F1,");
		query.append(" FECHA_MODIFICA = TO_DATE(SYSDATE, 'dd/mm/RRRR'), TERMINAL_MODIFICA = :TERMINAL_MODIFICA ");
		query.append(" WHERE SAB_CODIGO = :SAB_CODIGO AND BOT_EMP_CODIGO = :BOT_EMP_CODIGO ");

		namedParameters.put("BOT_EMP_CODIGO", atr.getBotEmpCodigo());
		namedParameters.put("SAB_CODIGO", atr.getSabCodigo());
		namedParameters.put("CAMPO_F1", atr.getFecha());
		namedParameters.put("USUARIO_MODIFICA", atr.getAuditoriaVO()
				.getUsuarioModifica());
		namedParameters.put("TERMINAL_MODIFICA", atr.getAuditoriaVO()
				.getTerminalModifica());
		namedParameters.put("strValor", atr.getVariable());

		System.out.println("query: " + query);
		for (String str : namedParameters.keySet()) {
			System.out.println(str + ": " + namedParameters.get(str));
		}
		return getNamedParameterJdbcTemplate().update(query.toString(),
				namedParameters);
	}

	private void updateBeneficioDisponible(Long codeSede, Long codeSubprograma)
			throws DAOException {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "";
		if ((Object) codeSede != null && (Object) codeSubprograma != null) {
			query = "SELECT MAX(codigo) codigo FROM tcs_ben_subprograma_sede "
					+ " WHERE sbpr_codigo = :sbpr_codigo AND sede_codigo = :sede_codigo ";

			namedParameters.put("sbpr_codigo", codeSubprograma);
			namedParameters.put("sede_codigo", codeSede);

			try {
				long codigo = getNamedParameterJdbcTemplate().queryForObject(
						query, namedParameters, Long.class);

				namedParameters.clear();
				query = "UPDATE  TCS_BEN_SUBPROGRAMA_SEDE "
						+ " SET NUMERO_BEN_DISPONIBLE = NUMERO_BEN_DISPONIBLE - 1 "
						+ " WHERE codigo = :codigo ";

				namedParameters.put("codigo", codigo);

				int iReg = getNamedParameterJdbcTemplate().update(query,
						namedParameters);
				if (iReg == 0) {
					throw new DAOException("");
				}
			} catch (IncorrectResultSizeDataAccessException e) {
				throw new DAOException(e);
			}
		}
	}

	private boolean checkBeneficio(Long codeSede, Long codeSubpro)
			throws DAOException {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		boolean retorno = false;
		if ((Object) codeSede == null || (Object) codeSubpro == null) {
			return retorno;
		}
		StringBuffer query = new StringBuffer(
				"SELECT NUMERO_BEN_DISPONIBLE "
						+ " FROM TCS_BEN_SUBPROGRAMA_SEDE WHERE SEDE_CODIGO = :SEDE_CODIGO AND SBPR_CODIGO = :SBPR_CODIGO ");

		namedParameters.put("SEDE_CODIGO", codeSede);
		namedParameters.put("SBPR_CODIGO", codeSubpro);

		try {
			int disponibles = getNamedParameterJdbcTemplate().queryForObject(
					query.toString(), namedParameters, Integer.class);
			if (disponibles > 0) {
				return true;
			}
		} catch (IncorrectResultSizeDataAccessException e) {
			return false;
		}
		return retorno;
	}

	private void aumentarBeneficioDisponible(Long codeSede, Long codeSubpro)
			throws DAOException {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "";
		if ((Object) codeSede != null && (Object) codeSubpro != null) {
			query = "SELECT MAX(codigo) codigo FROM tcs_ben_subprograma_sede "
					+ " WHERE sbpr_codigo = :sbpr_codigo AND sede_codigo = :sede_codigo ";

			boolean found = false;
			Long codigo = null;

			namedParameters.put("sbpr_codigo", codeSubpro);
			namedParameters.put("sede_codigo", codeSede);

			try {
				codigo = getNamedParameterJdbcTemplate().queryForObject(query,
						namedParameters, Long.class);
				found = true;
			} catch (IncorrectResultSizeDataAccessException e) {
				throw new DAOException(e);
			}

			if (found) {
				namedParameters.clear();
				query = "UPDATE  TCS_BEN_SUBPROGRAMA_SEDE "
						+ " SET NUMERO_BEN_DISPONIBLE = NUMERO_BEN_DISPONIBLE + 1 "
						+ " WHERE codigo = :codigo ";

				namedParameters.put("codigo", codigo);
				getNamedParameterJdbcTemplate().update(query, namedParameters);
			}

		}
	}

	private boolean existeBOTEmpresaAtr(Long codeBOTEmp, Long codeSAB) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT COUNT(1) cant "
				+ " FROM TCS_BOT_EMPRESA_ATR "
				+ " WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO AND SAB_CODIGO = :SAB_CODIGO";
		namedParameters.put("BOT_EMP_CODIGO", codeBOTEmp);
		namedParameters.put("SAB_CODIGO", codeSAB);
		int cant = 0;
		try {
			cant = getNamedParameterJdbcTemplate().queryForObject(query,
					namedParameters, Integer.class);
		} catch (IncorrectResultSizeDataAccessException e) {
		}
		if (cant == 1) {
			return true;
		}
		return false;
	}

	@Override
	public BeneficioOtorgadoEmpresaVO findBOT(Long codeBOT) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT CODIGO, SBPR_CODIGO, EMP_CODIGO, SEDE_CODIGO, TERCERO, VIGENCIA_BENEFICIO, "
				+ " PRESUP_TOT_EJECUTADO, USUARIO_CREA, TO_CHAR(FECHA_CREA, 'dd/MM/yyyy') FECHA_CREA, TERMINAL_CREA, USUARIO_MODIFICA, TO_CHAR(FECHA_MODIFICA,'dd/MM/yyyy') FECHA_MODIFICA, "
				+ " TERMINAL_MODIFICA, CAMPO_A1, DESPLAZADO, CAMPO_A3, TIPO_BENEFICIO, CAMPO_A5, CAMPO_A6, CAMPO_N1, "
				+ " CAMPO_N2, CAMPO_N3, CAMPO_F1, CAMPO_F2, CAMPO_F3, VALOR_BENEFICIO, TO_CHAR(FECHA_MEDICION, 'dd/MM/yyyy') FECHA_MEDICION "
				+ " FROM TCS_BOT_EMPRESA WHERE CODIGO = :CODIGO";
		namedParameters.put("CODIGO", codeBOT);

		BeneficioOtorgadoEmpresaVO vo = getNamedParameterJdbcTemplate()
				.queryForObject(query, namedParameters,
						new RowMapper<BeneficioOtorgadoEmpresaVO>() {

							@Override
							public BeneficioOtorgadoEmpresaVO mapRow(
									ResultSet rs, int arg1) throws SQLException {
								BeneficioOtorgadoEmpresaVO vo = new BeneficioOtorgadoEmpresaVO();
								vo.setCodigo(rs.getLong("CODIGO"));
								vo.setSbprCodigo(rs.getLong("SBPR_CODIGO"));
								vo.setEmpCodigo(rs.getLong("EMP_CODIGO"));
								vo.setSedeCodigo(rs.getLong("SEDE_CODIGO"));
								vo.setTercero(rs.getString("TERCERO"));
								vo.setVigenciaBeneficio(rs
										.getString("VIGENCIA_BENEFICIO"));
								vo.setPresupTotEjecutado(rs
										.getLong("PRESUP_TOT_EJECUTADO"));
								vo.setUsuarioCrea(rs.getString("USUARIO_CREA"));
								vo.setFechaCrea(rs.getString("FECHA_CREA"));
								vo.setTerminalCrea(rs
										.getString("TERMINAL_CREA"));
								vo.setUsuarioModifica(rs
										.getString("USUARIO_MODIFICA"));
								vo.setFechaModifica(rs
										.getString("FECHA_MODIFICA"));
								vo.setTerminalModifica(rs
										.getString("TERMINAL_MODIFICA"));
								vo.setCampoA1(rs.getString("CAMPO_A1"));
								vo.setDesplazado(rs.getString("DESPLAZADO"));
								vo.setCampoA3(rs.getString("CAMPO_A3"));
								vo.setTipoBeneficio(rs
										.getString("TIPO_BENEFICIO"));
								vo.setCampoA5(rs.getString("CAMPO_A5"));
								vo.setCampoA6(rs.getString("CAMPO_A6"));
								vo.setCampoN1(rs.getLong("CAMPO_N1"));
								vo.setCampoN2(rs.getLong("CAMPO_N2"));
								vo.setCampoN3(rs.getLong("CAMPO_N3"));
								vo.setCampoF1(rs.getString("CAMPO_F1"));
								vo.setCampoF2(rs.getString("CAMPO_F2"));
								vo.setCampoF3(rs.getString("CAMPO_F3"));
								vo.setValorBeneficio(rs
										.getLong("VALOR_BENEFICIO"));
								vo.setFechaMedicion(rs
										.getString("FECHA_MEDICION"));
								return vo;
							}
						});
		return vo;
	}

	@Override
	public boolean tieneBeneficio(Long empCodigo, Long sbprCodigo) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		namedParameters.put("EMP_CODIGO", empCodigo);
		namedParameters.put("SBPR_CODIGO", sbprCodigo);

		List<Map<String, Object>> ret = getNamedParameterJdbcTemplate()
				.queryForList(TIENE_BENEFICIO, namedParameters);

		if (ret != null && ret.size() > 0) {
			return true;
		}
		return false;
	}

	@Override
	public boolean otorgarBeneficio(
			BeneficioOtorgadoEmpresaVO beneficioOtorgadoEmpresaVO,
			List<Beneficiario_AtributoVO> lInsert) {
		boolean retorno = true;

		boolean cantidad = checkBeneficio(
				beneficioOtorgadoEmpresaVO.getSedeCodigo(),
				beneficioOtorgadoEmpresaVO.getSbprCodigo());

		boolean sw = false;

		if (cantidad) {
			int tamanoinsert = lInsert.size();

			// int insertbienBeneOtorgado = subprogramaServiceImpl2
			// .insertBeneficioOtorgado(strArr, i, fechaBeneficio);

			Long codeBOTInsertado = insertBOT(beneficioOtorgadoEmpresaVO);
			beneficioOtorgadoEmpresaVO.setCodigo(codeBOTInsertado);

			// fin del proceso

			if (beneficioOtorgadoEmpresaVO.getTercero() == null) {
				sw = true;
			} else {
				if (beneficioOtorgadoEmpresaVO.getTercero().equals("")) {
					sw = true;
				}
			}

			// Proceso para actualizar la cantidad disponible
			if (sw) {
				updateBeneficioDisponible(
						beneficioOtorgadoEmpresaVO.getSedeCodigo(),
						beneficioOtorgadoEmpresaVO.getSbprCodigo());
			}
			// fin del proceso

			// proceso para calcular el codigo maximo en la tabla beneficio
			// otorgado
			// String codMaxBenefOtor = subprogramaServiceImpl2
			// .findCodMaxBenOtor();
			// fin del proceso

			for (int j = 0; j < tamanoinsert; j++) {
				Beneficiario_AtributoVO objBenAtri = (Beneficiario_AtributoVO) lInsert
						.get(j);

				if (objBenAtri.getVariable().trim().equals("") == false) {
					if ((objBenAtri.getTipoatributo()).equals("R")) {
						// int insertobeneficiarioatri = atributosServiceImpl
						// .insertBeneficiarioAtri(
						// objBenAtri.getVariable().trim(),
						// objBenAtri.getTipodato(),
						// new Long(objBenAtri.getCodigoatributo()),
						// new Long(objBenAtri
						// .getCodbeneficiario()), i,
						// strArrIns);
					} else {
						// int insertobeneficioatri = atributosServiceImpl
						// .insertBeneficioAtri(
						// objBenAtri.getVariable().trim(),
						// objBenAtri.getTipodato(),
						// new Long(objBenAtri.getCodigoatributo()),
						// new Long(codMaxBenefOtor), i, strArrIns);
						BOTEmpresaAtr atr = new BOTEmpresaAtr();
						atr.setSabCodigo(Long.valueOf(objBenAtri
								.getCodigoatributo()));
						atr.setBotEmpCodigo(beneficioOtorgadoEmpresaVO
								.getCodigo());
						atr.getAuditoriaVO()
								.setUsuarioModifica(
										beneficioOtorgadoEmpresaVO
												.getUsuarioModifica());
						atr.getAuditoriaVO().setTerminalModifica(
								beneficioOtorgadoEmpresaVO
										.getTerminalModifica());
						atr.getAuditoriaVO()
								.setUsuarioCrea(
										beneficioOtorgadoEmpresaVO
												.getUsuarioModifica());
						atr.getAuditoriaVO().setTerminalCrea(
								beneficioOtorgadoEmpresaVO
										.getTerminalModifica());
						atr.setTipoDato(objBenAtri.getTipodato());
						atr.setVariable(objBenAtri.getVariable().trim());

						int updatedBOTEmpresaAtr = upsertBOTEmpresaAtr(atr);
					}
				}
			}
		} else {
			retorno = false;
		}
		return retorno;
	}

	/**
	 * 
	 * @param beneficioOtorgadoEmpresaVO
	 * @return CODIGO del beneficio otorgado que se inserta, null en caso de no
	 *         realizarse el insert.
	 */
	private Long insertBOT(BeneficioOtorgadoEmpresaVO beneficioOtorgadoEmpresaVO) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "INSERT INTO TCS_BOT_EMPRESA (CODIGO, SBPR_CODIGO, "
				+ " EMP_CODIGO, SEDE_CODIGO, TERCERO, VIGENCIA_BENEFICIO, PRESUP_TOT_EJECUTADO, "
				+ " USUARIO_CREA, FECHA_CREA, TERMINAL_CREA, USUARIO_MODIFICA, FECHA_MODIFICA, "
				+ " TERMINAL_MODIFICA, CAMPO_A1, DESPLAZADO, TIPO_BENEFICIO,"
				+ " VALOR_BENEFICIO, FECHA_MEDICION) "
				+ " VALUES(SCS_BOT_EMP.NEXTVAL, :SBPR_CODIGO, :EMP_CODIGO, :SEDE_CODIGO, "
				+ " :TERCERO, TO_NUMBER(:VIGENCIA_BENEFICIO), :PRESUP_TOT_EJECUTADO, :USUARIO_CREA, "
				+ " SYSDATE, :TERMINAL_CREA, :USUARIO_MODIFICA, SYSDATE, "
				+ " :TERMINAL_MODIFICA, :CAMPO_A1, :DESPLAZADO, :TIPO_BENEFICIO, "
				+ " :VALOR_BENEFICIO, :FECHA_MEDICION)";

		namedParameters.put("SBPR_CODIGO",
				beneficioOtorgadoEmpresaVO.getSbprCodigo());
		namedParameters.put("EMP_CODIGO",
				beneficioOtorgadoEmpresaVO.getEmpCodigo());
		namedParameters.put("SEDE_CODIGO",
				beneficioOtorgadoEmpresaVO.getSedeCodigo());
		namedParameters.put("TERCERO", beneficioOtorgadoEmpresaVO.getTercero());
		namedParameters.put("VIGENCIA_BENEFICIO",
				beneficioOtorgadoEmpresaVO.getVigenciaBeneficio());
		namedParameters.put("PRESUP_TOT_EJECUTADO",
				beneficioOtorgadoEmpresaVO.getPresupTotEjecutado());
		namedParameters.put("USUARIO_CREA",
				beneficioOtorgadoEmpresaVO.getUsuarioCrea());
		namedParameters.put("TERMINAL_CREA",
				beneficioOtorgadoEmpresaVO.getTerminalCrea());
		namedParameters.put("USUARIO_MODIFICA",
				beneficioOtorgadoEmpresaVO.getUsuarioModifica());
		namedParameters.put("TERMINAL_MODIFICA",
				beneficioOtorgadoEmpresaVO.getTerminalModifica());
		namedParameters
				.put("CAMPO_A1", beneficioOtorgadoEmpresaVO.getCampoA1());
		namedParameters.put("DESPLAZADO",
				beneficioOtorgadoEmpresaVO.getDesplazado());
		namedParameters.put("TIPO_BENEFICIO",
				beneficioOtorgadoEmpresaVO.getTipoBeneficio());
		namedParameters.put("VALOR_BENEFICIO",
				beneficioOtorgadoEmpresaVO.getValorBeneficio());
		namedParameters.put("FECHA_MEDICION",
				beneficioOtorgadoEmpresaVO.getFechaMedicion());
		System.out.println(query);
		for (String s : namedParameters.keySet()) {
			System.out.println(s + ":" + namedParameters.get(s));
		}
		GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
		SqlParameterSource parameterSource = new MapSqlParameterSource(
				namedParameters);
		getNamedParameterJdbcTemplate().update(query, parameterSource,
				generatedKeyHolder, new String[] { "CODIGO" });

		return generatedKeyHolder.getKey().longValue();
	}

	@Override
	public Long findUltimoCodeBOTBySbpr(Long codeSubpro, Long codeEmpresa) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		namedParameters.put("SBPR_CODIGO", codeSubpro);
		namedParameters.put("EMP_CODIGO", codeEmpresa);

		System.out.println("sbpr_codigo: " + codeSubpro);
		System.out.println("emp_codigo: " + codeEmpresa);

		Long code = null;
		try {
			code = getNamedParameterJdbcTemplate()
					.queryForObject(
							SELECT_MAX_COD_BENEFICIO_OTORGADO_EMPRESA_BY_SUBP_COD_BEN_COD,
							namedParameters, Long.class);
		} catch (IncorrectResultSizeDataAccessException e) {
		}
		return code;
	}

	@Override
	public String findValorBOTAtr(String tipoDato, Long codeBOT, Long codeAtri) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String consulta = "";
		if (tipoDato.equals("N")) {
			consulta = SELECT_BOT_EMPRESA_ATR_VALOR_NUM_ATR;
		} else if (tipoDato.equals("F")) {
			consulta = SELECT_BOT_EMPRESA_ATR_VALOR_FEC_ATR;
		} else {
			consulta = SELECT_BOT_EMPRESA_ATR_VALOR_CAR_ATR;
		}

		namedParameters.put("BOT_EMP_CODIGO", codeBOT);
		namedParameters.put("SAB_CODIGO", codeAtri);

		try {
			return getNamedParameterJdbcTemplate().queryForObject(consulta,
					namedParameters, String.class);
		} catch (IncorrectResultSizeDataAccessException e) {
			return null;
		}
	}

	@Override
	public boolean deleteBOT(Long codeBOT) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = " SELECT SBPR_CODIGO, SEDE_CODIGO "
				+ " FROM TCS_BOT_EMPRESA WHERE CODIGO = :CODIGO ";
		long codeSede;
		long codeSub;
		int delete;

		namedParameters.put("CODIGO", codeBOT);
		SubprogramaSedeVO cods = getNamedParameterJdbcTemplate()
				.queryForObject(query, namedParameters,
						new RowMapper<SubprogramaSedeVO>() {
							public SubprogramaSedeVO mapRow(ResultSet rs,
									int rowNum) throws SQLException {
								SubprogramaSedeVO vo = new SubprogramaSedeVO();
								vo.setCodeSubprograma(rs.getLong("SBPR_CODIGO"));
								vo.setCodeSede(rs.getLong("SEDE_CODIGO"));
								return vo;
							}
						});
		codeSede = cods.getCodeSede();
		codeSub = cods.getCodeSubprograma();

		query = " DELETE FROM TCS_BOT_EMPRESA_ATR "
				+ " WHERE BOT_EMP_CODIGO = :BOT_EMP_CODIGO ";

		// reusar
		namedParameters.clear();
		namedParameters.put("BOT_EMP_CODIGO", codeBOT);
		delete = getNamedParameterJdbcTemplate().update(query, namedParameters);

		query = " DELETE FROM TCS_BOT_EMPRESA " + " WHERE codigo = :codigo ";

		// reusar
		namedParameters.clear();
		namedParameters.put("codigo", codeBOT);
		delete += getNamedParameterJdbcTemplate()
				.update(query, namedParameters);

		if (delete > 0) {
			query = "SELECT MAX(codigo) codigo FROM tcs_ben_subprograma_sede "
					+ " WHERE sbpr_codigo = :sbpr_codigo AND sede_codigo = :sede_codigo ";

			// reusar
			namedParameters.clear();
			namedParameters.put("sbpr_codigo", codeSub);
			namedParameters.put("sede_codigo", codeSede);
			try {
				long code = getNamedParameterJdbcTemplate().queryForObject(
						query, namedParameters, Long.class);

				query = "UPDATE  TCS_BEN_SUBPROGRAMA_SEDE "
						+ " SET NUMERO_BEN_DISPONIBLE = NUMERO_BEN_DISPONIBLE + 1 "
						+ " WHERE codigo = :codigo ";
				namedParameters.clear();
				namedParameters.put("codigo", code);
				int update = getNamedParameterJdbcTemplate().update(query,
						namedParameters);
				if (update > 0) {
					return true;
				} else {
					throw new DAOException("");
				}

			} catch (IncorrectResultSizeDataAccessException e) {
				throw new DAOException(e);
			}
		}
		// TODO:
		throw new DAOException("");
	}

	@Override
	public boolean validarDeleteBOT(String groupUserName, String userName,
			Long codeBOT) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT COUNT(1) cantidad " + " FROM VCS_BOT_EMPRESA "
				+ " WHERE ('ADMINISTRADOR GENERAL' = :groupUserName "
				+ " OR 'SUPER USUARIO' = :groupUserName "
				+ " OR USUARIOCREA = :userName ) AND CODBOT = :codeBOT ";

		namedParameters.put("groupUserName", groupUserName);
		namedParameters.put("userName", userName);
		namedParameters.put("codeBOT", codeBOT);
		try {
			int cantidad = getNamedParameterJdbcTemplate().queryForObject(
					query, namedParameters, Integer.class);
			if (cantidad > 0) {
				return true;
			} else {
				return false;
			}
		} catch (IncorrectResultSizeDataAccessException e) {
			return false;
		}
	}
}
